import java.util.ArrayList;

public class Symbol
{
	//Symbol's name
	private String name;
	//Is Symbol terminal or non-terminal
	private boolean isTerminal;
	//Derivations for non-terminal Symbols
	private ArrayList<String> derivations;
	//Is this Symbol's first set complete?
	private boolean firstComplete;
	//Symbol first set, meant for non-terminal Symbols
	private ArrayList<String> firstSet;
	//Symbol follow set, meant for non-terminal Symbols
	private ArrayList<String> followSet;
	
	public Symbol(String name, boolean terminal)
	{
		this.name = name.trim();
		isTerminal = terminal;
		derivations = new ArrayList<String>();;
		firstSet = new ArrayList<String>();
		followSet = new ArrayList<String>();
		firstComplete = false;
	}
	
	public Symbol(String name, boolean terminal, String deriv)
	{
		this.name = name.trim();
		isTerminal = terminal;
		derivations = new ArrayList<String>();
		derivations.add(deriv);
		firstSet = new ArrayList<String>();
		followSet = new ArrayList<String>();
		firstComplete = false;
	}
	
	public Symbol(String name, boolean terminal, ArrayList<String> derivs)
	{
		this.name = name.trim();
		isTerminal = terminal;
		derivations = derivs; 
		firstSet = new ArrayList<String>();
		followSet = new ArrayList<String>();
		firstComplete = false;
	}
	
	public void addDerivation(String s)
	{
		if(!derivations.contains(s))
		{
			if(s.length() == 0)
				derivations.add("\\epsilon");
			else
				derivations.add(s);
		}
	}
	
	/**
	 * @return the name
	 */
	public String getName()
	{
		return name;
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name)
	{
		this.name = name.trim();
	}
	
	public boolean isFirstComplete()
	{
		return firstComplete;
	}

	public void setFirstComplete(boolean firstComplete)
	{
		this.firstComplete = firstComplete;
	}

	/**
	 * @return the isTerminal
	 */
	public boolean isTerminal()
	{
		return isTerminal;
	}

	/**
	 * @param isTerminal the isTerminal to set
	 */
	public void setTerminal(boolean isTerminal)
	{
		this.isTerminal = isTerminal;
	}

	/**
	 * @return the derivations
	 */
	public ArrayList<String> getDerivations()
	{
		return derivations;
	}

	/**
	 * @param derivations the derivations to set
	 */
	public void setDerivations(ArrayList<String> derivations)
	{
		this.derivations = derivations;
	}
	
	public void setFirstSet(ArrayList<String> firstSet)
	{
		this.firstSet = firstSet;
	}

	public void setFollowSet(ArrayList<String> followSet)
	{
		this.followSet = followSet;
	}

	public void addToFirstSet(String addedItem)
	{
		if(!firstSet.contains(addedItem))
		{
			firstSet.add(addedItem);
		}

	}
	
	public void addToFollowSet(String addedItem)
	{
		if(!followSet.contains(addedItem))
		{
			followSet.add(addedItem);
		}
	}
	
	public ArrayList<String> getFirstSet()
	{
		return firstSet;
	}
	
	public ArrayList<String> getFollowSet()
	{
		return followSet;
	}
	
	public String toString()
	{
		String ret = "";
		for(int i = 0; i < derivations.size(); i++)
		{
			ret += name + " --> " + derivations.get(i) + "; ";
		}
		
		return ret;
	}

}
